#include "FightManager.h"
#include "stdio.h"
namespace SLG
{
	FightManager::FightManager(LPDIRECT3DDEVICE9 device,
		FigureObject* fo)
		:g_pd3dDevice(device),
		m_Figure(fo)

	{
	}

	FightManager::~FightManager(void)
	{
	}

	bool FightManager::AddModel(int32 mid,const char* name,const char* fname)
	{
		Model* model=new Model;
		//char f[256];
		//strcpy_s(f,256,name);
		//strcat_s(f,256,".m2");
		if(!LoadM2(fname,model))
			return false;
		int32 tid=LoadTga(fname);
		if(tid==-1)
			return false;
		m_Figure->AddModel(mid,tid,(char*)name,model);
		return true;
	}

	char* FightManager::_getSkinName(const char* p)
	{
		char* rt=new char[256];
		char* q=rt;
		strcpy_s(rt,256,p);
		assert(rt&&*rt);
		int8 size=0;
		q++;
		while(*q!='\0'&&*q!='.')
		{
			size++;
			q++;
		}
		strcpy_s(q,256-size,"00.skin");
		return rt;
	}

	char* FightManager::_getFileName(char* p)
	{
		char* rt=NULL;
		assert(p&&*p);
		while(*p!='\0')
		{
			if(*p == '\\')
			{
				rt=p;
			}
			p++;
		}
		rt++;
		return rt;
	}

	bool FightManager::AddFigure(int32 id,int32 mid,const char* name,int32 x,int32 y,int32 face)
	{
		m_Figure->AddFigure(id,mid,(const char*)name,x,y,(FACE)face);
		return true;
	}

	int32 FightManager::LoadTga(const char* filename)
	{
		char* tga=new char[256];
		strcpy_s(tga,256,filename);
		char* q=&tga[strlen(tga)];
		assert(tga&&*tga);
		uint32 i=0;
		while(q!=tga&&*q!='.')
		{
			i++;
			q--;
		}
		assert(q&&*q);
		strcpy(q,".tga");
		LPDIRECT3DTEXTURE9 tex;
		if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,tga,&tex)))
		{
			return -1;
		}
		return m_Figure->AddTexture(tga,tex);
	}

	bool FightManager::LoadM2(const char* f,Model* model)
	{

		FILE* fp=NULL;
		FILE* fp2=NULL;
		DWORD err=fopen_s(&fp,f,"rb");
		if(err)
		{
			return false;
		}

		char* skinName=_getSkinName(f);
		err=fopen_s(&fp2,skinName,"rb");
		if(err)
		{
			return false;
		}

		size_t offset=0;

		//ModelType modelType;
		//vector < char* > vTextureName;
		//char* texName;

		model->header=new ModelHeader;
		
		fread(model->header,sizeof(ModelHeader),1,fp);
		ModelHeader* header=model->header;

		offset=header->ofsVertices;
		model->vertices = new ModelVertex[header->nVertices];
		fseek(fp,offset,SEEK_SET);
		fread(model->vertices,sizeof(ModelVertex),header->nVertices,fp);
		for(size_t i=0;i<header->nVertices;i++)
		{
			model->vertices[i].pos=fixCoordSystem(model->vertices[i].pos);
		}

		//model->vertices3D=new D3DXVECTOR3[header->nVertices];

		//offset=header->ofsTextures;
		//ModelTextureDef* texdef = new ModelTextureDef[header->nTextures];
		//memcpy(texdef,bufferM2+offset,sizeof(ModelTextureDef)*header->nTextures);

		offset=header->ofsGlobalSequences;
		uint32* globalSequences = new uint32[header->nGlobalSequences];
		fseek(fp,header->ofsGlobalSequences,SEEK_SET);
		fread(globalSequences,sizeof(uint32),header->nGlobalSequences,fp);

		/*if (header->nTextures) 
		{
		TextureID* textures = new TextureID[header->nTextures];
		for (size_t i=0; i<header->nTextures; i++) 
		{
		if (i > TEXTURE_MAX-1) 
		{
		break;
		}

		if (texdef[i].type == TEXTURE_FILENAME) 
		{
		texName=(char*)(bufferM2+texdef[i].nameOfs);
		//LoadBLP(_getFileName(texName),i);
		} 
		}
		}*/

		if (header->nColors) 
		{
			model->colors = new ModelColor[header->nColors];
			ModelColorDef *colorDefs = new ModelColorDef[header->nColors];
			fseek(fp,header->ofsColors,SEEK_SET);
			fread(colorDefs,sizeof(ModelColorDef),header->nColors,fp);
			for (size_t i=0; i<header->nColors; i++) 
				model->colors[i].init(fp, colorDefs[i], globalSequences);
			delete[] colorDefs;
		}

		// init transparency
		if (header->nTransparency) {
			model->transparency = new ModelTransparency[header->nTransparency];
			ModelTransDef *trDefs = new ModelTransDef[header->nTransparency];
			fseek(fp,header->ofsTransparency,SEEK_SET);
			fread(trDefs,sizeof(ModelTransDef),header->nTransparency,fp);
			for (size_t i=0; i<header->nTransparency; i++) 
				model->transparency[i].init(fp, trDefs[i], globalSequences);
			delete[] trDefs;
		}

		ModelView view;
		fseek(fp2,0,SEEK_SET);
		fread(&view,sizeof(ModelView),1,fp2);

		uint16 *indexLookup = new uint16[view.nIndex];
		offset=view.ofsIndex;
		fseek(fp2,offset,SEEK_SET);
		fread(indexLookup,sizeof(uint16),view.nIndex,fp2);
		uint16 *triangles = new uint16[view.nTris];
		fseek(fp2,view.ofsTris,SEEK_SET);
		fread(triangles,sizeof(uint16),view.nTris,fp2);
		uint32 nIndices = view.nTris;
		model->indices = new uint16[nIndices];
		for (size_t i = 0; i<nIndices; i++) 
		{
			model->indices[i] = indexLookup[triangles[i]];
		}


		uint16 *transLookup = new uint16[header->nTransparencyLookup];
		fseek(fp,header->ofsTransparency,SEEK_SET);
		fread(transLookup,sizeof(uint16),header->nTransparency,fp);

		ModelGeoset *ops = new ModelGeoset[view.nSub];
		fseek(fp2,view.ofsSub,SEEK_SET);
		fread(ops,sizeof(ModelGeoset),view.nSub,fp2);

		ModelTexUnit *tex = new ModelTexUnit[view.nTex];
		fseek(fp2,view.ofsTex,SEEK_SET);
		fread(tex,sizeof(ModelTexUnit),view.nTex,fp2);

		ModelRenderFlags* renderFlags = new ModelRenderFlags[header->nTexFlags];
		fseek(fp,header->ofsTexFlags,SEEK_SET);
		fread(renderFlags,sizeof(ModelRenderFlags),header->nTexFlags,fp);
		uint16* texlookup = new uint16[header->nTexLookup];
		fseek(fp,header->ofsTexLookup,SEEK_SET);
		fread(texlookup,sizeof(uint16),header->nTexLookup,fp);
		/*bool* showGeosets = new bool[view.nSub];
		for (size_t i=0; i<view.nSub; i++) 
		{
			showGeosets[i] = true;
		}*/


		for (size_t j = 0; j<view.nTex; j++) 
		{
			size_t geoset = tex[j].op;
			Map temp;
			temp.indexStart = ops[geoset].istart;
			temp.indexCount = ops[geoset].icount;
			temp.vertexStart = ops[geoset].vstart;
			temp.vertexEnd = ops[geoset].vcount;

			temp.tex = texlookup[tex[j].textureid];

			// TODO: figure out these flags properly -_-
			ModelRenderFlags &rf = renderFlags[tex[j].flagsIndex];

			temp.blendmode = rf.blend;

			temp.color = tex[j].colorIndex;
			temp.opacity = transLookup[tex[j].transid];

			// ToDo: Work out the correct way to get the true/false of transparency
			temp.trans = (temp.blendmode>0) && (temp.opacity>0);	// Transparency - not the correct way to get transparency

			temp.p = ops[geoset].BoundingBox[0].z;


			temp.m_pVB=NULL;
			model->RenderMap.push_back(temp);

		}

		ModelAnimation* anims = new ModelAnimation[header->nAnimations];
		ModelAnimationWotLK* animsWotLK=new ModelAnimationWotLK[header->nAnimations];

		fseek(fp,header->ofsAnimations,SEEK_SET);
		fread(animsWotLK,sizeof(ModelAnimationWotLK),header->nAnimations,fp);
		for(size_t i=0; i<header->nAnimations; i++) 
		{
			anims[i].animID = animsWotLK[i].animID;
			anims[i].timeStart = 0;
			anims[i].timeEnd = animsWotLK[i].length;
			anims[i].moveSpeed = animsWotLK[i].moveSpeed;
			anims[i].flags = animsWotLK[i].flags;
			anims[i].probability = animsWotLK[i].probability;
			anims[i].d1 = animsWotLK[i].d1;
			anims[i].d2 = animsWotLK[i].d2;
			anims[i].playSpeed = animsWotLK[i].playSpeed;
			anims[i].boundSphere.min = animsWotLK[i].boundSphere.min;
			anims[i].boundSphere.max = animsWotLK[i].boundSphere.max;
			anims[i].boundSphere.radius = animsWotLK[i].boundSphere.radius;
			anims[i].NextAnimation = animsWotLK[i].NextAnimation;
			anims[i].Index = animsWotLK[i].Index;
		}
		model->anims=anims;

		ModelBoneDef* boneDef= new ModelBoneDef[header->nBones];
		fseek(fp,header->ofsBones,SEEK_SET);
		fread(boneDef,sizeof(ModelBoneDef),header->nBones,fp);

		Bone* bones = new Bone[header->nBones];
		for (size_t i=0; i<header->nBones; i++) 
		{
			bones[i].initV3(fp, boneDef[i], globalSequences, NULL);
		}
		model->bones=bones;
		delete[] boneDef;
		delete[] animsWotLK;
		delete[] texlookup;
		
		delete[] renderFlags;
		delete[] globalSequences;
		delete[] ops;
		delete[] tex;
		//delete(transLookup);
		delete[] triangles;
		delete[] indexLookup;
		fclose(fp);
		fclose(fp2);
		return true;
	}

}